package edu.upol.paradise.runtime;

import java.util.ArrayList;
import java.util.List;

import edu.upol.paradise.compiler.types.Nil;
import edu.upol.paradise.compiler.types.ParadiseObject;
import edu.upol.paradise.compiler.types.ParadisePair;
import edu.upol.paradise.compiler.types.ParadiseSymbol;

public class FunctionArgumentsHeader {

	protected static final String ANY = "(ANY)";

	public static FunctionArgumentsHeader parse(String args) {
		FunctionArgumentsHeader header = new FunctionArgumentsHeader();
		
		if (args.equals(ANY)){
			header.setListArg(true);
			header.setListArgName("args");
		} else {
			// parse from string
			String[] dotSplit = args.split("\\.");
			if (dotSplit.length == 2){
				header.setListArg(true);
				header.setListArgName(dotSplit[1].trim());
			}
			String[] argList = dotSplit[0].split(" ");
			for (String arg : argList){
				arg = arg.trim();
				header.getArgs().add(arg);
			}
		}
		
		return header;
	}
	
	public static FunctionArgumentsHeader parse(ParadiseObject methodDesc) {
		FunctionArgumentsHeader header = new FunctionArgumentsHeader();
		if (methodDesc.isAtom()){
			header.setListArg(true);
			header.setListArgName(methodDesc.toString());
		} else {
			ParadisePair p = (ParadisePair)methodDesc;
			while (p != Nil.NIL){
				ParadiseSymbol sym = (ParadiseSymbol) p.car();
				header.getArgs().add(sym.toString());
				if (p.cdr().isAtom()){
					header.getArgs().add(p.cdr().toString());
					p = Nil.NIL;
				} else {
					p = (ParadisePair) p.cdr();
				}
			}
		}
		return header;
	}
	
	private boolean listArg = false; // whether we append all remaining arguments into a list or not
	private String  listArgName = "args"; // list arg name
	private List<String> args = new ArrayList<String>();
	
	public boolean isListArg() {
		return listArg;
	}
	
	private void setListArg(boolean listArg) {
		this.listArg = listArg;
	}

	public String getListArgName() {
		return listArgName;
	}

	private void setListArgName(String listArgName) {
		this.listArgName = listArgName;
	}
	
	public List<String> getArgs() {
		return args;
	}	
}
